package com.woniuxy.cloud.carl.user.app.apiImpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu.cloud.Aspect.log.Log;
import com.woniuxy.cloud.carl.user.app.util.JwtUtil;
import com.woniuxy.cloud.carl.user.client.UserManageClient;
import com.woniuxy.cloud.carl.user.client.param.LoginByEmailParam;
import com.woniuxy.cloud.carl.user.client.param.LoginByPhoneParam;
import com.woniuxy.cloud.carl.user.client.param.RegisterParam;
import com.woniuxy.cloud.carl.user.client.param.SetUserInfoParam;
import com.woniuxy.cloud.carl.user.common.ContantsDate;
import com.woniuxy.cloud.carl.user.common.RedisKey;
import com.woniuxy.cloud.carl.user.common.UserResultCode;
import com.woniuxy.cloud.carl.user.infra.model.User;
import com.woniuxy.cloud.carl.user.service.UserService;
import com.woniuxy.cloud.carl.user.service.param.LoginServiceParam;
import com.woniuxy.cloud.carl.user.service.param.RegisterServiceParam;
import com.woniuxy.exceptions.MallException;
import com.woniuxy.result.Result;
import org.redisson.api.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("user")
public class UserManageApiImpl implements UserManageClient {

    @Resource
    private UserService userService;
    @Resource
    private RedissonClient redissonClient;

//    @GetMapping("test")
//    public Result testR(){
//        RMapCache<String, Integer> myMap = redissonClient.getMapCache("myMap");
//        myMap.put("xx",1,7,TimeUnit.DAYS);
//        return Result.success();
//    }
//
//    @GetMapping("getRedis")
//    public Result getRedisson(){
//        RMapCache<String, Integer> myMap = redissonClient.getMapCache("myMap");
//        Integer integer = myMap.get("test");
//        if(integer==null) return Result.fail("miss");
//        return Result.success(integer);
//    }



    @Override
    @Log(value = "通过电话登录")
    public Result<String> loginByPhone(LoginByPhoneParam param) {
        //判断账号存在
        User user = userService.getOne(new QueryWrapper<User>().eq("user_phone", param.getUserPhone()));
        if(user==null) throw new MallException(UserResultCode.USER_NOT_EXIST);
        //判断redis中存Key
        RMapCache<String, String> map = redissonClient.getMapCache(RedisKey.USER_LOGIN_CODE);
        if(!map.containsKey(param.getUserPhone())) throw new MallException(UserResultCode.CODE_ILLEGAL);
        //判断验证码
        String code = map.get(param.getUserPhone());
        if(code==null) throw new MallException(UserResultCode.CODE_ILLEGAL);
        if(!code.equals(param.getCode())) throw new MallException(UserResultCode.CODE_ILLEGAL);

        LoginServiceParam serviceParam = BeanUtil.toBean(param, LoginServiceParam.class);
        Long userId =userService.login(serviceParam);
        HashMap<String, Object> body = new HashMap<>();
        body.put("sub",userId);
        body.put("role",1);
        Integer minites = 30;
        String accessToken = JwtUtil.createToken(body,minites);
        return Result.success(accessToken);

    }

    @Override
    @Log(value = "通过邮箱登录")
    public Result<String> loginByEmail(LoginByEmailParam param) {
        //判断账号存在
        User user = userService.getOne(new QueryWrapper<User>().eq("user_email", param.getUserEmail()));
        if(user==null) throw new MallException(UserResultCode.USER_NOT_EXIST);
        //判断密码
        if(param.getUserPassword()!=null){
            if(!user.getUserPassword().equals(param.getUserPassword())) throw new MallException(UserResultCode.PWD_NOT_MATCH);
        }else{
            throw new MallException(UserResultCode.PARAMETER_ILLEGAL);
        }
        //登录 生成token
        LoginServiceParam serviceParam = BeanUtil.toBean(param, LoginServiceParam.class);
        Long userId =userService.login(serviceParam);
        HashMap<String, Object> body = new HashMap<>();
        body.put("sub",userId);
        body.put("role",1);
        Integer minites = 300;
        String accessToken = JwtUtil.createToken(body,minites);
        return Result.success(accessToken);

    }

    @Transactional
    @Override
    @Log(value = "用户注册")
    public Result register(RegisterParam registerParam) {
        //判断账号重复
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_email", registerParam.getUserEmail()).or().eq("user_phone",registerParam.getUserPhone());
        User user = userService.getOne(wrapper);
        if(user!=null) throw new MallException(UserResultCode.USER_REGISTERED);
        //密码不为空
        if(registerParam.getUserPassword()==null) throw new MallException(UserResultCode.PARAMETER_ILLEGAL);
        //注册
        RegisterServiceParam param = BeanUtil.toBean(registerParam, RegisterServiceParam.class);
        userService.register(param);
        return Result.success();
    }

    @Override
    @Log(value = "设置用户头像")
    public Result setAvatar(String avatarUrl,Long userId) {
        User user = userService.getById(userId);
        if(user==null) throw new MallException(UserResultCode.USER_NOT_EXIST);
        user.setAvatar(avatarUrl);
        userService.saveOrUpdate(user);
        return Result.success();
    }

    @Override
    @Log(value = "修改用户基本信息")
    public Result setUserInfo(SetUserInfoParam setUserInfoParam) {
        User user = userService.getById(setUserInfoParam.getUserId());
        if(user==null) throw new MallException(UserResultCode.USER_NOT_EXIST);
        User email = userService.getOne(new QueryWrapper<User>().eq("user_email", setUserInfoParam.getEmail())
                .ne("user_id",setUserInfoParam.getUserId()));
        if(email!=null) throw new MallException(UserResultCode.USER_REGISTERED);
        user.setUserEmail(setUserInfoParam.getEmail());
        user.setAvatar(setUserInfoParam.getAvatar());
        user.setUserName(setUserInfoParam.getUserName());
        userService.saveOrUpdate(user);
        return Result.success();
    }

    @Override
    @Log(value = "用户成为vip")
    public Result beVip(Long userId) {
        User user = userService.getById(userId);
        if(user==null) throw new MallException(UserResultCode.USER_NOT_EXIST);
        user.setVip(ContantsDate.USER_VIP);
        DateTime dateTime = DateUtil.nextMonth();
        user.setEndTime(dateTime);
        userService.saveOrUpdate(user);
        return Result.success();
    }

    @Override
    @Log(value = "修改用户积分")
    public Result setScore(Long userId, BigDecimal amount) {
        User user = userService.getById(userId);
        if(user==null) throw new MallException(UserResultCode.USER_NOT_EXIST);
        BigDecimal divide = amount.divide(new BigDecimal(10));
        Integer score = divide.intValue();
        user.setScore(user.getScore()+score);
        userService.saveOrUpdate(user);
        return Result.success();
    }

    @Override
    @Log(value = "用户修改密码")
    public Result setPwd(Long userId, String userPassword) {
        User user = userService.getById(userId);
        if(user==null) throw new MallException(UserResultCode.USER_NOT_EXIST);
        user.setUserPassword(userPassword);
        userService.saveOrUpdate(user);
        return Result.success();
    }

    @Override
    @Log(value = "发送注册验证码")
    public Result sendRegCode(String userPhone) {
        //判断一分钟内是否已经发过
        RMapCache<String, String> registerMInMap = redissonClient.getMapCache(RedisKey.REGISTER_CODE_IN_MIN);
        if(!registerMInMap.containsKey(userPhone)) throw new MallException(UserResultCode.CODE_USE_TO_MUCH);
        //判断一小时内是否已经第五次了
        RMapCache<String, Integer> map = redissonClient.getMapCache(RedisKey.REGISTER_CODE_IN_HOURS);
        if(map.containsKey(userPhone)){
            Integer time = map.get(userPhone);
            if(time==5) throw new MallException(UserResultCode.ACCOUNT_CODE_MUCH_5);
        }
//        String code = SMSUtil.send(phone);
        //存入五分钟的code
        String code = "123321";
        RMapCache<String, String> RegMap = redissonClient.getMapCache(RedisKey.USER_REGISTER_CODE);
        RegMap.put(userPhone,code,300,TimeUnit.SECONDS);
        //一分钟内只能发一次
        RMapCache<String, String> mapInMin = redissonClient.getMapCache(RedisKey.REGISTER_CODE_IN_MIN);
        mapInMin.put(userPhone,userPhone,60,TimeUnit.SECONDS);
        //一个小时只能发5次
        RMapCache<String, Integer> mapInHour = redissonClient.getMapCache(RedisKey.REGISTER_CODE_IN_HOURS);
        if(!mapInHour.containsKey(userPhone)){
            mapInHour.put(userPhone,0,1,TimeUnit.HOURS);
        }
        mapInHour.put(userPhone,map.get(userPhone)+1);
        return Result.success();
    }

    @Override
    @Log(value = "发送登录验证码")
    public Result sendLoginCode(String userPhone) {
        //判断一分钟内是否已经发过
        RMapCache<String, String> LoginInMap = redissonClient.getMapCache(RedisKey.LOGIN_CODE_IN_MIN);
        if(LoginInMap.containsKey(userPhone)) throw new MallException(UserResultCode.CODE_USE_TO_MUCH);
        //判断一小时内是否已经第五次了
        RMapCache<String, Integer> map = redissonClient.getMapCache(RedisKey.LOGIN_CODE_IN_HOURS);
        if(map.containsKey(userPhone)){
            Integer time = map.get(userPhone);
            if(time==5) throw new MallException(UserResultCode.ACCOUNT_CODE_MUCH_5);
        }
//        String code = SMSUtil.send(phone);
        //存入五分钟的code
        String code = "123321";
        RMapCache<String, String> RegMap = redissonClient.getMapCache(RedisKey.USER_LOGIN_CODE);
        RegMap.put(userPhone,code,300,TimeUnit.SECONDS);
        //一分钟内只能发一次
        RMapCache<String, String> mapInMin = redissonClient.getMapCache(RedisKey.LOGIN_CODE_IN_MIN);
        mapInMin.put(userPhone,userPhone,60,TimeUnit.SECONDS);
        //一个小时只能发5次
        RMapCache<String, Integer> mapInHour = redissonClient.getMapCache(RedisKey.LOGIN_CODE_IN_HOURS);
        if(!mapInHour.containsKey(userPhone)){
            mapInHour.put(userPhone,0,1,TimeUnit.HOURS);
        }
        mapInHour.put(userPhone,map.get(userPhone)+1);
        return Result.success();
    }

    @Override
    @Log(value = "积分兑换")
    public Result useCode(Long userId, Integer score) {
        User user = userService.getById(userId);
        Integer newScore =user.getScore()-score;
        if(newScore<0){
            throw new MallException(UserResultCode.SCORE_NOT_ENOUGHT);
        }
        user.setScore(newScore);
        userService.saveOrUpdate(user);
        return Result.success();
    }


}
